#!/bin/bash

# ============================================================
# OHOS 测试服务器管理脚本
# 用途：统一管理所有测试服务器的启动、停止和状态查看
# ============================================================

# 颜色定义
RESET='\033[0m'
BOLD='\033[1m'
RED='\033[31m'
GREEN='\033[32m'
YELLOW='\033[33m'
BLUE='\033[34m'
CYAN='\033[36m'
BG_BLUE='\033[44m'

# 项目根目录
PROJECT_ROOT=$(cd "$(dirname "$0")" && pwd)
cd "$PROJECT_ROOT" || exit 1

# 日志目录
LOGS_DIR="$PROJECT_ROOT/logs"
mkdir -p "$LOGS_DIR"

# PID 文件目录
PIDS_DIR="$PROJECT_ROOT/pids"
mkdir -p "$PIDS_DIR"

# ============================================================
# 工具函数
# ============================================================

print_header() {
    echo -e "${BOLD}${BG_BLUE}==================== $1 ====================${RESET}"
}

print_success() {
    echo -e "${GREEN}✅ $1${RESET}"
}

print_error() {
    echo -e "${RED}❌ $1${RESET}"
}

print_info() {
    echo -e "${CYAN}ℹ️  $1${RESET}"
}

print_warning() {
    echo -e "${YELLOW}⚠️  $1${RESET}"
}

# 检查并生成证书
check_and_generate_certs() {
    local CERT_DIR="$PROJECT_ROOT/cert"
    
    if [ -f "$CERT_DIR/server.crt" ] && [ -f "$CERT_DIR/server.key" ]; then
        return 0
    fi
    
    print_warning "未找到证书文件，正在自动生成..."
    echo ""
    
    mkdir -p "$CERT_DIR"
    cd "$CERT_DIR" || return 1
    
    # 生成服务器证书
    openssl req -x509 -newkey rsa:2048 -nodes \
        -keyout server.key \
        -out server.crt \
        -days 365 \
        -subj "/C=CN/ST=Test/L=Test/O=OHOS/CN=localhost" \
        -addext "subjectAltName=DNS:localhost,DNS:*.local,IP:127.0.0.1,IP:0.0.0.0" \
        2>/dev/null
    
    if [ $? -eq 0 ]; then
        print_success "测试证书生成成功"
        print_info "证书位置: $CERT_DIR/"
        echo ""
    else
        print_error "证书生成失败"
        print_warning "HTTPS 服务器可能无法启动"
        echo ""
    fi
    
    cd "$PROJECT_ROOT" || exit 1
}

# ============================================================
# 服务器管理函数
# ============================================================

# 启动 DNS 服务器
start_dns() {
    print_info "Starting DNS Server..."
    cd "$PROJECT_ROOT/server/ohos_dns_server" || return 1
    
    if [ ! -d "node_modules" ]; then
        npm install
    fi
    
    nohup npm start > "$LOGS_DIR/dns_server.log" 2>&1 &
    echo $! > "$PIDS_DIR/dns.pid"
    
    print_success "DNS Server started (PID: $!)"
    print_info "Port: 53 (UDP)"
    print_info "Log: $LOGS_DIR/dns_server.log"
}

# 启动 MQTT 服务器
start_mqtt() {
    print_info "Starting MQTT Server..."
    cd "$PROJECT_ROOT/server/ohos_mqtt_server" || return 1
    
    if [ ! -f "go.mod" ]; then
        go mod init mqtt_server
        go mod tidy
    fi
    
    nohup go run main.go > "$LOGS_DIR/mqtt_server.log" 2>&1 &
    echo $! > "$PIDS_DIR/mqtt.pid"
    
    print_success "MQTT Server started (PID: $!)"
    print_info "TCP Port: 1883"
    print_info "WebSocket Port: 1882"
    print_info "Stats Port: 8080"
    print_info "Log: $LOGS_DIR/mqtt_server.log"
}

# 启动 Socket.IO 服务器
start_socketio() {
    print_info "Starting Socket.IO Server..."
    cd "$PROJECT_ROOT/server/ohos_socketio_tls_server" || return 1
    
    if [ ! -d "node_modules" ]; then
        npm install
    fi
    
    nohup npm start > "$LOGS_DIR/socketio_server.log" 2>&1 &
    echo $! > "$PIDS_DIR/socketio.pid"
    
    print_success "Socket.IO Server started (PID: $!)"
    print_info "HTTP Port: 3100"
    print_info "HTTPS Port: 3101"
    print_info "Log: $LOGS_DIR/socketio_server.log"
}

# 启动 Axios 服务器
start_axios() {
    print_info "Starting Axios/HTTP Server..."
    
    # 检查证书（HTTPS 服务器需要）
    check_and_generate_certs
    
    cd "$PROJECT_ROOT/server/ohos_axios_server" || return 1
    
    if [ ! -d "node_modules" ]; then
        npm install
    fi
    
    mkdir -p upload public
    
    nohup npm start > "$LOGS_DIR/axios_server.log" 2>&1 &
    echo $! > "$PIDS_DIR/axios.pid"
    
    print_success "Axios Server started (PID: $!)"
    print_info "HTTP: 4000"
    print_info "HTTPS (basic): 4001"
    print_info "HTTPS (mutual + pwd): 4002"
    print_info "HTTPS (mutual): 4003"
    print_info "HTTPS (TLS 1.2): 4004"
    print_info "HTTP/2: 4005"
    print_info "Log: $LOGS_DIR/axios_server.log"
}

# 启动静态文件服务器（用于证书下载）
start_static() {
    print_info "Starting Static File Server (Certificate Download)..."
    
    # 检查 http-server 是否安装
    if ! command -v http-server &> /dev/null; then
        print_warning "http-server not found, installing..."
        npm install -g http-server
    fi
    
    # 确保证书目录存在
    mkdir -p "$PROJECT_ROOT/cert"
    
    cd "$PROJECT_ROOT/cert" || return 1
    nohup http-server --port 4006 --cors > "$LOGS_DIR/static_server.log" 2>&1 &
    echo $! > "$PIDS_DIR/static.pid"
    
    print_success "Static Server started (PID: $!)"
    print_info "Port: 4006"
    print_info "Certificate Download: http://localhost:4006/"
    print_info "  - server.crt: http://localhost:4006/server.crt"
    print_info "  - server.key: http://localhost:4006/server.key"
    print_info "  - client.crt: http://localhost:4006/client.crt (if exists)"
    print_info "  - client.key: http://localhost:4006/client.key (if exists)"
    print_info "Log: $LOGS_DIR/static_server.log"
}

# 启动代理服务器
start_proxy() {
    print_info "Starting Proxy Server..."
    
    if ! command -v tinyproxy &> /dev/null; then
        print_error "tinyproxy not installed"
        return 1
    fi
    
    tinyproxy -c "$PROJECT_ROOT/tinyproxy.conf"
    
    print_success "Proxy Server started"
    print_info "Port: 8005"
}

# 停止服务器
stop_server() {
    local name=$1
    local pid_file="$PIDS_DIR/${name}.pid"
    
    if [ -f "$pid_file" ]; then
        local pid=$(cat "$pid_file")
        if ps -p "$pid" > /dev/null 2>&1; then
            kill "$pid"
            print_success "$name server stopped (PID: $pid)"
        else
            print_warning "$name server not running"
        fi
        rm -f "$pid_file"
    else
        print_warning "No PID file found for $name"
    fi
}

# 查看服务器状态
check_status() {
    print_header "Server Status"
    
    for server in dns mqtt socketio axios static; do
        local pid_file="$PIDS_DIR/${server}.pid"
        if [ -f "$pid_file" ]; then
            local pid=$(cat "$pid_file")
            if ps -p "$pid" > /dev/null 2>&1; then
                print_success "$server: Running (PID: $pid)"
            else
                print_error "$server: Stopped (stale PID file)"
                rm -f "$pid_file"
            fi
        else
            print_error "$server: Stopped"
        fi
    done
    
    # 检查代理
    if pgrep tinyproxy > /dev/null; then
        print_success "proxy: Running"
    else
        print_error "proxy: Stopped"
    fi
}

# 查看日志
view_logs() {
    local server=$1
    local log_file="$LOGS_DIR/${server}_server.log"
    
    if [ -f "$log_file" ]; then
        tail -f "$log_file"
    else
        print_error "Log file not found: $log_file"
    fi
}

# ============================================================
# 主函数
# ============================================================

show_help() {
    echo "Usage: $0 {start|stop|restart|status|logs} [server_name]"
    echo ""
    echo "Commands:"
    echo "  start [all|dns|mqtt|socketio|axios|static|proxy]  - Start server(s)"
    echo "  stop [all|dns|mqtt|socketio|axios|static|proxy]   - Stop server(s)"
    echo "  restart [all|dns|mqtt|socketio|axios|static|proxy] - Restart server(s)"
    echo "  status                                             - Show server status"
    echo "  logs [dns|mqtt|socketio|axios|static]              - View server logs"
    echo ""
    echo "Examples:"
    echo "  $0 start all          - Start all servers"
    echo "  $0 start mqtt         - Start only MQTT server"
    echo "  $0 stop all           - Stop all servers"
    echo "  $0 status             - Check status of all servers"
    echo "  $0 logs mqtt          - View MQTT server logs"
}

start_all() {
    print_header "Starting All Servers"
    
    # 首先检查并生成证书
    check_and_generate_certs
    
    start_dns
    sleep 1
    start_mqtt
    sleep 1
    start_socketio
    sleep 1
    start_axios
    sleep 1
    start_static
    sleep 1
    start_proxy
    
    echo ""
    PUBLIC_IP=$(curl -s ifconfig.me)
    print_header "All Servers Started"
    print_success "Public IP: $PUBLIC_IP"
    print_info "Run '$0 status' to check server status"
}

stop_all() {
    print_header "Stopping All Servers"
    stop_server dns
    stop_server mqtt
    stop_server socketio
    stop_server axios
    stop_server static
    
    # 停止代理
    if pgrep tinyproxy > /dev/null; then
        pkill tinyproxy
        print_success "Proxy server stopped"
    fi
    
    print_header "All Servers Stopped"
}

# 主命令处理
case "$1" in
    start)
        case "$2" in
            all|"")
                start_all
                ;;
            dns)
                start_dns
                ;;
            mqtt)
                start_mqtt
                ;;
            socketio)
                start_socketio
                ;;
            axios)
                start_axios
                ;;
            static)
                start_static
                ;;
            proxy)
                start_proxy
                ;;
            *)
                print_error "Unknown server: $2"
                show_help
                exit 1
                ;;
        esac
        ;;
    stop)
        case "$2" in
            all|"")
                stop_all
                ;;
            dns|mqtt|socketio|axios|static)
                stop_server "$2"
                ;;
            proxy)
                pkill tinyproxy && print_success "Proxy stopped" || print_error "Proxy not running"
                ;;
            *)
                print_error "Unknown server: $2"
                show_help
                exit 1
                ;;
        esac
        ;;
    restart)
        case "$2" in
            all|"")
                stop_all
                sleep 2
                start_all
                ;;
            dns|mqtt|socketio|axios|static|proxy)
                stop_server "$2"
                sleep 1
                start_$2
                ;;
            *)
                print_error "Unknown server: $2"
                show_help
                exit 1
                ;;
        esac
        ;;
    status)
        check_status
        ;;
    logs)
        if [ -z "$2" ]; then
            print_error "Please specify a server name"
            show_help
            exit 1
        fi
        view_logs "$2"
        ;;
    *)
        show_help
        exit 1
        ;;
esac

exit 0
